package db

import (
	"core/rds"
	"core/utils"
	"fmt"
	"strings"
)

type LevelDetail struct {
	Unlock    bool `json:"unlock"`
	FinishNum int  `json:"finish_num"`
	Love      bool `json:"love"`
}

func MakeUserLevelKey(uid int64) string {
	return fmt.Sprintf("user:%d:level", uid)
}
func encodeLevelDetail(detail *LevelDetail) (out string) {
	return fmt.Sprintf("%t:%d", detail.Unlock, detail.FinishNum)
}
func decodeLevelDetail(in string) (detail *LevelDetail) {
	detail = new(LevelDetail)
	fmt.Fscanf(strings.NewReader(in), "%t:%d", &detail.Unlock, &detail.FinishNum)
	return
}

func EncodeLove(menuId, levelId int) string {
	return fmt.Sprintf("%d:%d", menuId, levelId)
}

func DecodeLove(key string) (menuId, levelId int) {
	fmt.Fscanf(strings.NewReader(key), "%d:%d", &menuId, &levelId)
	return
}

func loadLevelData(u *User) (err error) {
	u.Level = make(map[int]map[int]LevelDetail)
	levelData, err := rds.GetCacheClient(u.UID).HGetAll(MakeUserLevelKey(u.UID)).Result()
	if err != nil {
		return
	}
	for k, v := range levelData {
		ids := strings.Split(k, ":")
		if len(ids) < 2 {
			continue
		}
		levelDetail := decodeLevelDetail(v)
		menuId := utils.ToInt(ids[0])
		levelId := utils.ToInt(ids[1])
		if u.Level[menuId] == nil {
			u.Level[menuId] = map[int]LevelDetail{levelId: *levelDetail}
		} else {
			u.Level[menuId][levelId] = *levelDetail
		}
	}
	return
}

func (u *User) SaveLevel(menuId, level int, levelDetail *LevelDetail) (err error) {
	userLevelKey := MakeUserLevelKey(u.UID)
	userLevelRedis := rds.GetCacheClient(u.UID)
	err = userLevelRedis.HMSet(userLevelKey, map[string]interface{}{
		fmt.Sprintf("%d:%d", menuId, level): encodeLevelDetail(levelDetail),
	}).Err()
	if err != nil {
		return
	}
	if u.Level[menuId] == nil {
		u.Level[menuId] = map[int]LevelDetail{level: *levelDetail}
	} else {
		u.Level[menuId][level] = *levelDetail
	}

	err = userLevelRedis.Expire(userLevelKey, userExpire).Err()
	err = userLevelRedis.Expire(MakeUserKey(u.UID), userExpire).Err()
	if err != nil {
		return
	}
	go AddActiveUser(u.UID)
	return
}
